package compile

import (
	"fmt"
	"io"
	"strconv"
)

const _SYNTAX_ERR_LIMIT = 300

type parser struct {
	scanner // build-in scanner

	hasError   bool
	_loopLevel int
	_errc      int

	_labels []string
}

func (self *parser) Failed() bool {
	return self.hasError
}

func (self *parser) syntaxError(msg string, exit bool) {
	self.hasError = true

	self._errc++

	if self._errc >= _SYNTAX_ERR_LIMIT {
		fmt.Println("[E] Parser crashed. Please report this bug to developer.")
		self.scanner._syntaxError(msg, true, 1)
	}

	self.scanner._syntaxError(msg, exit, 1)
}

func (self *parser) posSyntaxError(msg string, exit bool, line, col int) {
	ln, cl := self.line, self.col
	self.line, self.col = line, col

	self.syntaxError(msg, exit)

	self.line, self.col = ln, cl
}

func (self *parser) init(reader io.Reader, name string) {
	self.scanner.init(reader, name)
}

func (self *parser) justExpect(tok token) bool {
	if self.tok != tok {
		self.syntaxError(
			fmt.Sprintf("Expecting %s, but found %s",
				getTokenName(tok), getTokenName(self.tok)), false)
		return false
	}
	return true
}

func (self *parser) expect(tok token) bool {
	b := self.justExpect(tok)

	if b {
		self.next()
	}

	return b
}

func (self *parser) expectOp(op operator) bool {
	b := self.compare(_OPERATOR)
	if !b || self.tokOp != op {
		self.syntaxError(
			fmt.Sprintf("Expecting %s, but found %s",
				getOperatorName(op), getTokenName(self.tok)), false)
		return false
	}
	self.next()
	return true
}

func (self *parser) want(tok token) bool {
	if !self.expect(tok) {
		self.next()
		return false
	}
	return true
}

func (self *parser) update(tok Token) {
	self.tok = self.scanner.tok
	self.tokOp = self.scanner.tokOp
	self.tokValue = self.scanner.tokValue
	self.tokNumType = self.scanner.tokNumType
	self.tokNumBase = self.scanner.tokNumBase
}

func (self *parser) compare(tok token) bool {
	if self.tok == tok {
		return true
	}
	return false
}

func (self *parser) got(tok token) bool {
	if self.tok == tok {
		self.next()
		return true
	}
	return false
}

func (self *parser) getIdentifier() *Identifier {
	id := new(Identifier)
	id.pos = *self.pos

	if self.compare(_IDENTIFIER) {
		id = &Identifier{Value: self.tokValue}
		self.next() // eat IDENTIFIER

		return id
	}
	self.syntaxError("Expecting IDENTIFIER", false)
	self.next()
	return id
}

func (self *parser) isOperator(op operator) bool {
	if self.compare(_OPERATOR) {
		return self.tokOp == op
	}
	return false
}

func (self *parser) _parseDotPath() *DotPath {
	dp := new(DotPath)
	dp.pos = *self.pos

	var parts []*Identifier

	v := self.getIdentifier()

	if v == nil {
		return dp
	}

	parts = append(parts, v)

	if !self.compare(_DOT) {
		dp.Parts = parts
		return dp
	}

	self.next() // eat '.'

	for self.isOperator(_MUIT) || self.compare(_IDENTIFIER) {
		if self.isOperator(_MUIT) {
			dp.WithWildcard = true
			self.next() // eat '*'
			break
		}

		v = self.getIdentifier()
		parts = append(parts, v)

		if !self.compare(_DOT) {
			break
		}

		self.next() // eat '.'
	}

	dp.Parts = parts

	return dp
}

func (self *parser) parsePackageDeclare() *PackageDeclare {
	self.expect(_PACKAGE)

	pd := &PackageDeclare{}
	pd.pos = *self.pos

	if self.tok == _DOT {
		self.next()
		self.expect(_SEMI)
		return pd
	}

	dpath := self._parseDotPath()
	if dpath.WithWildcard {
		self.syntaxError("Excepting identifier", false)
		self.next()
	}

	pd.PackagePath = dpath

	self.expect(_SEMI)

	return pd
}

func (self *parser) parseImportDeclare() *ImportDeclare {
	self.expect(_IMPORT) // eat 'import'

	static := self.got(_STATIC)

	impd := &ImportDeclare{}
	impd.pos = *self.pos
	impd.IsStatic = static

	path := self._parseDotPath()

	if self.compare(_AS) {
		// check
		if path.WithWildcard {
			self.syntaxError("Cannot use 'as' when importing a package", false)
		}

		if static {
			self.syntaxError("Cannot use 'as' while import statically", false)
		}

		self.next() // eat 'as'
		v := self.getIdentifier()

		if v == nil {
			return nil
		}
		impd.Name = v.Value
	} else if len(path.Parts) > 0 {
		impd.Name = path.Parts[len(path.Parts)-1].Value
	}

	impd.WithWildcard = path.WithWildcard
	impd.ImportParts = path

	self.expect(_SEMI) // eat ';'

	return impd
}

func (self *parser) parseArrayDecls(needSize bool) []*ArrayDeclare {
	if !self.compare(_LBRACK) {
		return nil
	}

	var al []*ArrayDeclare

	for self.got(_LBRACK) {
		ad := new(ArrayDeclare)
		var exp Expression

		if self.compare(_RBRACK) {
			exp = nil
		} else {
			exp = self.parseExpression()
		}

		if !needSize && exp != nil {
			self.syntaxError("No size decl", false)
		}

		ad = &ArrayDeclare{Size: exp}
		ad.pos = *self.pos

		al = append(al, ad)

		self.expect(_RBRACK)
	}

	return al
}

func (self *parser) _parseGenericTypes() []*TypeExpr {
	self.expectOp(_LTH)

	tlist := make([]*TypeExpr, 0)

	for !self.compare(_GTH) && !self.compare(_EOF) {
		t := self.parseTypeExpr(true)
		tlist = append(tlist, t)

		if !self.got(_COMMA) {
			break
		}
	}

	self.expectOp(_GTH)

	return tlist
}

func (self *parser) _parseClassAccessCell() *ClassAccessCell {
	c := &ClassAccessCell{}
	c.pos = *self.pos

	if !self.justExpect(_IDENTIFIER) {
		return nil
	}

	c.ClassName = self.tokValue

	self.nextSingle()

	if !self.isOperator(_LTH) {
		return c
	}

	self.nextSingle() // eat '<'

	generic := []*TypeExpr{}

	fcac := self.parseTypeExpr(false)
	generic = append(generic, fcac)

	for self.got(_COMMA) {
		cac := self.parseTypeExpr(false)
		generic = append(generic, cac)
	}

	if !self.isOperator(_GTH) {
		self.syntaxError("Expecting _GTH", false)
		self.next()
		return c
	}
	self.nextSingle()

	c.GenericTypes = generic

	return c
}

func (self *parser) parseClassAccessExpr() *ClassAccessExpr {
	cacc := &ClassAccessExpr{}
	cacc.pos = *self.pos

	cels := make([]*ClassAccessCell, 0)

	fcel := self._parseClassAccessCell()
	cels = append(cels, fcel)

	for self.got(_DOT) {
		cel := self._parseClassAccessCell()
		cels = append(cels, cel)
	}

	cacc.Classes = cels

	return cacc
}

func (self *parser) parseTypeFactor() *TypeFactor {
	if !self.compare(_IDENTIFIER) {
		self.syntaxError("Expecting IDENTIFIER", false)
		return nil
	}

	factor := new(TypeFactor)
	factor.pos = *self.pos

	if isBaseType(self.tokValue) {
		id := self.getIdentifier()
		id.Value = checkBeasTypeAlias(id.Value)
		factor.BaseType = id
		return factor
	} else {
		utype := self.parseClassAccessExpr()
		factor.UserType = utype
		return factor
	}
}

func (self *parser) parseTypeExpr(simpleDecl bool) *TypeExpr {
	pos := *self.pos
	arrd := self.parseArrayDecls(!simpleDecl)
	tfactor := self.parseTypeFactor()

	texpr := new(TypeExpr)
	texpr.pos = pos
	texpr.ArrayDecls = arrd
	texpr.Factor = tfactor

	return texpr
}

func (self *parser) parseArrayBody(depth int) *ArrayBody {
	self.expect(_LBRACE)

	body := new(ArrayBody)
	body.ArrDepth = depth

	expl := make([]Expression, 0)

	if self.compare(_RBRACE) {
		self.next()
		body.Items = expl
		return body
	}

	var fitem Expression

	if !self.compare(_LBRACE) {
		fitem = self.parseExpression()
	} else {
		fitem = self.parseArrayBody(depth + 1)
	}

	expl = append(expl, fitem)

	for self.got(_COMMA) {
		var exp Expression
		if !self.compare(_LBRACE) {
			exp = self.parseExpression()
		} else {
			exp = self.parseArrayBody(depth + 1)
		}
		expl = append(expl, exp)
	}

	self.expect(_RBRACE)

	body.Items = expl

	return body
}

func (self *parser) _parseAnonymousClassDecl() *AnonymousClassDecl {
	clsd := new(AnonymousClassDecl)
	clsd.pos = *self.pos

	self.expect(_CLASS)

	clsd.BaseClass = self.parseClassAccessExpr()
	clsd.Members, clsd.OpOverloads = self.parseClassBody("<Anonymous class>", false)

	return clsd
}

func (self *parser) _parseOverrideClassDecl() *OverrideClassDecl {
	clsd := new(OverrideClassDecl)
	clsd.pos = *self.pos

	self.expect(_OVERRIDE)

	clsd.OverrideClass = self.parseClassAccessExpr()
	clsd.Block = self.parseBlock(false)

	return clsd
}

func (self *parser) parseThrowStmt() *ThrowStmt {
	stmt := new(ThrowStmt)
	self.expect(_THROW)

	if !self.compare(_SEMI) {
		stmt.Expr = self.parseExpression()
	}
	self.expect(_SEMI)

	return stmt
}

func (self *parser) parseAssertStmt() *AssertStmt {
	stmt := new(AssertStmt)
	self.expect(_ASSERT)

	stmt.Expr = self.parseExpression()

	self.expect(_SEMI)

	return stmt
}

func (self *parser) parseNewExpr() *NewExpr {
	self.expect(_NEW)
	newexpr := new(NewExpr)
	newexpr.pos = *self.pos

	if self.compare(_CLASS) {
		newexpr.AnonymousClass = self._parseAnonymousClassDecl()

		return newexpr

	} else if self.compare(_OVERRIDE) {
		newexpr.OverrideClass = self._parseOverrideClassDecl()

		return newexpr
	}

	texpr := self.parseTypeExpr(true)
	newexpr.Type = texpr

	switch self.tok {

	case _LPAREN:
		if texpr.Factor.BaseType != nil {
			self.syntaxError("Unexpected Declaration", false)
		}
		argv := self.parseArgList()
		newexpr.ArgList = argv

	case _LBRACE:
		// Check
		if texpr.ArrayDecls == nil {
			self.syntaxError("Unexpected Declaration", false)
		}

		arbody := self.parseArrayBody(1)

		newexpr.ArrFactor = arbody

	default:
		self.syntaxError("Expecting _LPAREN or _LBRACE", false)
		self.next()
	}

	return newexpr
}

func (self *parser) parseArgList() *ArgList {
	self.expect(_LPAREN)

	al := &ArgList{}
	al.pos = *self.pos

	expl := []Expression{}

	if self.compare(_RPAREN) {
		self.next()
		return al
	}

	farg := self.parseExpression()
	expl = append(expl, farg)

	for self.compare(_COMMA) {
		self.next()
		exp := self.parseExpression()
		expl = append(expl, exp)
	}

	al.PlainArg = expl

	self.expect(_RPAREN)

	return al
}

func (self *parser) _toCallOrNot(right Expression, temp Expression, left Expression) Expression {
	exp, ok := right.(*CallExpr)
	l, ojbk := temp.(*AccessExpr)

	if !ok || !ojbk {
		return temp
	}

	l.Right = exp.Left
	exp.Left = l

	return exp
}

func (self *parser) parseCallSubscrAccessExpr() Expression {
	var left Expression

	left = self.parseCellExpr()

	for {
		switch self.tok {

		case _LBRACK:
			self.next()

			value := self.parseExpression()

			temp := &SubscrExpr{}
			temp.pos = *self.pos
			temp.Right = value
			temp.Left = left

			self.expect(_RBRACK)

		case _DOT:
			self.next()
			value := self.parseExpression()

			temp := &AccessExpr{}
			temp.pos = *self.pos
			temp.Right = value
			temp.Left = left

			left = self._toCallOrNot(value, temp, left)

		default:
			return left
		}
	}
}

func (self *parser) parseUnaryExpr() Expression {
	var beh bool // for Increase Expr
	var incOp token
	var incTarg Expression

	pos := *self.pos

	switch self.tok {
	case _OPERATOR:
		if self.tokOp == _SUBSUB || self.tokOp == _PLUSPLUS {
			incOp = self.tok
			beh = false
			self.next() // eat op
			incTarg = self.parseCallSubscrAccessExpr()
			goto incExpr

		} else if self.tokOp <= _BNG && self.tokOp >= _PLUS {
			unre := &NormalUnaryExpr{}
			unre.pos = pos

			unre.Op = self.tok
			self.next() // eat 'op'
			unre.Right = self.parseCallSubscrAccessExpr()

			return unre
		} else if self.tokOp == _NOT {
			self.expectOp(_NOT)
			exp := self.parseExpression()
			nexp := new(NotExpr)
			nexp.pos = *self.pos
			nexp.Right = exp

			return nexp
		} else if self.tokOp == _LTH {
			return self.parseCallSubscrAccessExpr()
		}
		return self.parseCallSubscrAccessExpr()

	default:
		r := self.parseCallSubscrAccessExpr()

		if self.compare(_OPERATOR) &&
			(self.tokOp == _PLUSPLUS || self.tokOp == _SUBSUB) {

			incTarg = r
			incOp = self.tok
			beh = true
			self.next() // eat op
			goto incExpr
		}
		return r
	}

incExpr:
	ince := &IncreaseExpr{}
	ince.pos = pos
	ince.Op = incOp
	ince.Behind = beh
	ince.Right = incTarg

	return ince
}

func (self *parser) fillCellNumber(cell *CellExpr, base numBase, numt numType) {
	cell.CellType = numt

	switch numt {
	case _LONG:
		v, _ := strconv.ParseInt(self.tokValue, base, 64)
		cell.Integer = uint64(v)

	case _INTEGER:
		v, _ := strconv.ParseInt(self.tokValue, base, 32)
		cell.Integer = uint64(v)

	case _FLOAT:
		v, _ := strconv.ParseFloat(self.tokValue, 32)
		cell.Float = v

	case _DOUBLE:
		v, _ := strconv.ParseFloat(self.tokValue, 64)
		cell.Float = v

	default:
		self.syntaxError("Expecting NUMBER", false)
		self.next()
		cell.CellType = _INTEGER
	}
}

func (self *parser) parseTypeConvertOrNil() *TypeConvertExpr {
	state := self.makeState()
	conv := new(TypeConvertExpr)
	conv.pos = *self.pos

	if !self.got(_LPAREN) {
		return nil
	}

	plevel := 1

	for {
		if self.compare(_EOF) {
			self.setState(state)
			return nil
		}

		if self.compare(_LPAREN) {
			plevel++
		}

		if self.compare(_RPAREN) {
			plevel--
		}

		if plevel == 0 || self.compare(_EOF) {
			break
		}

		self.next()
	} // jump after rparen

	self.expect(_RPAREN)

	switch self.tok {

	case _NUMBER, _IDENTIFIER, _LPAREN, _NEW, _STRING:
		// Do nothing
	default:
		self.setState(state)
		return nil

	}

	// Go back to parse type expr
	self.setState(state)
	self.expect(_LPAREN)
	t := self.parseTypeExpr(true)

	conv.Type = t

	self.expect(_RPAREN)

	return conv
}

func (self *parser) parseCellExpr() Expression {
	cell := &CellExpr{}
	cell.pos = *self.pos

	cell.CellType = self.tok
	cell.Raw = self.tokValue

	var result Expression = cell

	var hasConv bool
	calGeneric := make([]*TypeExpr, 0)

	if self.isOperator(_LTH) {
		calGeneric = self._parseGenericTypes()
	}

	// Cell includes Call expr
	// Need to check tok is '<' or not.

	// check type convert
	conv := self.parseTypeConvertOrNil()
	hasConv = conv != nil

	switch self.tok {

	case _NEW:
		result = self.parseNewExpr()

		goto noNext

	case _LPAREN:
		self.next() // eat '('
		exp := self.parseExpression()
		self.expect(_RPAREN)
		result = exp

		goto noNext

	case _NUMBER:
		self.fillCellNumber(cell, self.tokNumBase, self.tokNumType)

	case _STRING:
		cell.String = self.tokValue
		cell.CellType = _STRING

	case _IDENTIFIER: // Call or Cell
		cell.Ident = self.tokValue
		cell.CellType = _IDENTIFIER

		pos := *self.pos
		self.next()

		if self.compare(_LPAREN) {
			argl := self.parseArgList()

			temp := &CallExpr{}
			temp.pos = pos
			temp.Left = cell
			temp.Args = argl
			temp.GenericTypes = calGeneric

			result = temp
		}

		goto noNext

	case _CHAR:
		cell.Ident = self.tokValue
		cell.CellType = _CHAR

	default:
		self.syntaxError(fmt.Sprintf("Expecting Exprssion, but found %s",
			getTokenName(self.tok)), false)
		goto noNext
	}

	self.next()

noNext:
	if _, ok := result.(*CallExpr); !ok && len(calGeneric) > 0 {
		self.syntaxError("Generic type decl can only use with Call Expr", false)
	}

	if hasConv {
		conv.Expr = result
		result = conv
	}

	return result
}

func (self *parser) parseFactorExpr() Expression {
	return self.parseUnaryExpr()
}

func (self *parser) parsePrimaryExpr() Expression {
	pos := *self.pos

	cond := self.parseFactorExpr()

	if self.got(_IF) {
		vA := self.parseExpression()
		self.expect(_ELSE)
		vB := self.parseExpression()

		tern := &TernaryExpr{}
		tern.pos = pos
		tern.Cond = cond
		tern.A = vA
		tern.B = vB

		return tern
	}

	return cond
}

func (self *parser) parseBinRHS(left Expression, prec int) Expression {
	for {
		cTokPrec := getOpPrec(self.tokOp, self.tok)

		if cTokPrec < prec {
			return left
		}

		curOp := self.tokOp
		var isAssignOp bool

		if self.tokOp == _ASSIGN_OP {
			isAssignOp = true
			curOp = self.tokAssignOp
		}

		self.next() // eat op

		rhs := self.parsePrimaryExpr()

		nTokPrec := getOpPrec(self.tokOp, self.tok)

		if nTokPrec > cTokPrec {
			rhs = self.parseBinRHS(rhs, nTokPrec+1)
		}

		left = &BinaryExpr{
			LHS:    left,
			RHS:    rhs,
			Op:     curOp,
			Assign: isAssignOp,
		}
	}
}

func (self *parser) parseExpression() Expression {
	left := self.parsePrimaryExpr()

	return self.parseBinRHS(left, 0)
}

func (self *parser) parseReturnStmt() *ReturnStmt {
	rtn := new(ReturnStmt)
	rtn.pos = *self.pos

	self.expect(_RETURN)

	if self.got(_SEMI) {
		return rtn
	}

	exp := self.parseExpression()
	if exp == nil {
		return nil
	}

	rtn.Expr = exp

	self.expect(_SEMI)

	return rtn
}

func (self *parser) parseVarStmt(inline bool, declOnly bool, needVar bool) *VarStmt {
	if !needVar {
		self.got(_VAR)
	} else {
		self.expect(_VAR)
	}

	stmt := new(VarStmt)
	stmt.pos = *self.pos

	names := make([]*Identifier, 0)

	fname := self.getIdentifier()
	if fname == nil {
		return stmt
	}

	names = append(names, fname)

	for self.got(_COMMA) {
		n := self.getIdentifier()
		names = append(names, n)
	}

	var texpr *TypeExpr

	if !self.isOperator(_ASSIGN) && !inline {
		texpr = self.parseTypeExpr(false)
	}

	var value Expression

	if self.isOperator(_ASSIGN) {
		if declOnly {
			self.syntaxError("Cannot set initial value", false)
		}
		self.next()
		value = self.parseExpression()
	}

	if !inline {
		self.expect(_SEMI)
	}

	stmt.Names = names
	stmt.Type = texpr
	stmt.Value = value

	return stmt
}

func (self *parser) parseBlock(inLoop bool) *BlockStmt {
	if !self.expect(_LBRACE) {
		return nil
	}

	block := new(BlockStmt)
	block.pos = *self.pos

	stmts := make([]Statement, 0)

	if inLoop {
		self._loopLevel++
	}

	if !self.compare(_RBRACE) {
		stmts = self.parseStmts()
	}

	self.expect(_RBRACE)

	if inLoop {
		self._loopLevel--
	}

	block.Stmts = stmts

	return block
}

func (self *parser) parseElifBlock() *IfStmt {
	self.expect(_ELIF)

	stmt := new(IfStmt)
	stmt.pos = *self.pos

	test := self.parseExpression()
	block := self.parseBlock(false)

	stmt.Test = test
	stmt.IfBody = block

	return stmt
}

func (self *parser) parseIfStmt(isElif bool) *IfStmt {
	self.expect(_IF)
	stmt := new(IfStmt)
	stmt.pos = *self.pos

	test := self.parseExpression()
	body := self.parseBlock(false)
	elifs := make([]*IfStmt, 0)
	var elseBlock *BlockStmt

	for self.compare(_ELIF) {
		elif := self.parseElifBlock()
		elifs = append(elifs, elif)
	}

	if self.got(_ELSE) {
		elseBlock = self.parseBlock(false)
	}

	for self.compare(_ELIF) {
		self.syntaxError("Elif block must between IF and ELSE block", false)
		_ = self.parseElifBlock()
	}

	stmt.Test = test
	stmt.IfBody = body
	stmt.Elifs = elifs
	stmt.ElseBody = elseBlock

	return stmt
}

func (self *parser) parseWhileStmt() *WhileStmt {
	self.expect(_WHILE)

	stmt := new(WhileStmt)
	stmt.pos = *self.pos

	test := self.parseExpression()
	body := self.parseBlock(true)

	if self.got(_THEN) {
		stmt.ThenBody = self.parseBlock(false)
	}

	stmt.Body = body
	stmt.Test = test

	return stmt
}

func (self *parser) _parseCatchCase() *CatchCase {
	c := new(CatchCase)
	c.pos = *self.pos

	self.expect(_CATCH)
	cFType := self.parseClassAccessExpr()
	if cFType.Classes == nil {
		return c
	}

	// check
	for _, cls := range cFType.Classes {
		if cls != nil && cls.GenericTypes != nil {
			self.syntaxError("Cannot use generic declaration in catch case", false)
		} else if cls == nil {
			self.next()
			return c
		}
	}

	self.expect(_AS)
	cName := self.getIdentifier()

	cBlock := self.parseBlock(false)

	c.Body = cBlock
	c.Name = cName
	c.Case = cFType

	return c
}

func (self *parser) parseTryStmt() *TryStmt {
	self.expect(_TRY)

	stmt := new(TryStmt)
	stmt.pos = *self.pos

	tBody := self.parseBlock(false)

	cases := make([]*CatchCase, 0)

	for self.compare(_CATCH) {
		c := self._parseCatchCase()
		cases = append(cases, c)
	}

	if len(cases) == 0 {
		self.syntaxError("Expecting catch block", false)
		self.next()
	}

	var fBlock *BlockStmt

	if self.compare(_FINALLY) {
		self.next() // eat 'finally'
		fBlock = self.parseBlock(false)
	}

	stmt.TryBlock = tBody
	stmt.Cases = cases
	stmt.Finally = fBlock

	return stmt
}
func (self *parser) _parseVarList() []*VarStmt {
	list := make([]*VarStmt, 0)

	list = append(list, self.parseVarStmt(true, false, false))

	for self.got(_COMMA) {
		list = append(list, self.parseVarStmt(true, false, false))
	}

	return list
}

func (self *parser) _parseForEachStmt() *ForEachStmt {
	// starts from VarStmt

	stmt := new(ForEachStmt)
	stmt.pos = *self.pos

	vard := self.parseVarStmt(true, true, false)
	if !self.compare(_COLON) { // if var stmt have type decl.
		vard.Type = self.parseTypeExpr(false)
	}
	self.expect(_COLON)
	obj := self.parseExpression()

	stmt.Var = vard
	stmt.Object = obj

	body := self.parseBlock(true)
	stmt.Body = body

	if self.got(_THEN) {
		stmt.ThenBody = self.parseBlock(false)
	}

	return stmt
}

func (self *parser) _parseClassicForStmt() *ForStmt {
	// starts from '('
	stmt := new(ForStmt)

	// Init
	init := make([]*VarStmt, 0)
	if !self.got(_SEMI) {
		init = self._parseVarList()
		self.expect(_SEMI)
	}
	var test Expression
	// Test
	if !self.got(_SEMI) {
		test = self.parseExpression()
		self.expect(_SEMI)
	}
	// Update

	upd := make([]Expression, 0)
	if !self.got(_RPAREN) {
		upd = self._parseExprList()
		self.expect(_RPAREN)
	}

	body := self.parseBlock(true)

	if self.got(_THEN) {
		stmt.ThenBody = self.parseBlock(false)
	}

	stmt.Init = init
	stmt.Test = test
	stmt.Update = upd
	stmt.Body = body

	return stmt
}

func (self *parser) parseForStmt() Statement {
	self.expect(_FOR)

	if !self.compare(_LPAREN) {
		return self._parseForEachStmt()
	}

	self.next() // eat '('
	return self._parseClassicForStmt()
}

func (self *parser) parseClassFile(name string) *ClassFile {
	clsf := new(ClassFile)

	// self.next() // initialize scanner

	if !self.compare(_PACKAGE) {
		self.syntaxError("SAIL Souce must starts with package statement.", true)
	}

	pkgd := self.parsePackageDeclare()
	impd := make([]*ImportDeclare, 0)
	decls := make([]MemberDeclare, 0)

	for self.compare(_IMPORT) {
		d := self.parseImportDeclare()
		impd = append(impd, d)
	}
	decls = self.parseOutsideDecls()

	var clsName string

	for _, d := range decls {
		switch d.(type) {

		case *ClassDeclare:
			c := d.(*ClassDeclare)
			if c.Property.AccessModifiers == ACC_PUBLIC {
				clsName = c.Name.Value
				break
			}
		case *InterfaceDeclare:
			i := d.(*InterfaceDeclare)
			if i.Property.AccessModifiers == ACC_PUBLIC {
				clsName = i.Name.Value
				break
			}
		case *EnumDeclare:
			e := d.(*EnumDeclare)
			if e.Property.AccessModifiers == ACC_PUBLIC {
				clsName = e.Name.Value
				break
			}
		}
	}

	clsf.Imports = impd
	clsf.Decls = decls
	clsf.ClassFileName = name
	clsf.ClassFilePath = self.sourceName
	clsf.PublicClassName = clsName
	clsf.Package = pkgd

	return clsf
}

func (self *parser) _parseExprList() []Expression {
	expl := make([]Expression, 0)
	f := self.parseExpression()
	expl = append(expl, f)

	for self.got(_COMMA) {
		e := self.parseExpression()
		expl = append(expl, e)
	}

	return expl
}

func (self *parser) _parseSwitchCase() *SwitchCase {
	pos := *self.pos

	var isDefault bool
	exprl := make([]Expression, 0)

	if self.got(_DEFAULT) {
		isDefault = true
	} else {
		self.expect(_CASE)
		for {
			exprl = append(exprl, self.parseExpression())

			if !self.got(_COMMA) {
				break
			}
		}
	}

	c := new(SwitchCase)
	c.pos = pos

	self.expect(_COLON)

	stmts := make([]Statement, 0)

	self._loopLevel++

	for !self.compare(_EOF) {
		if self.compare(_DEFAULT) || self.compare(_CASE) || self.compare(_RBRACE) {
			break
		}

		if self.tok == _CONTINUE && self._loopLevel == 1 {
			self.syntaxError("Continue inside switch", false)
		}

		stmt := self.parseStmt()

		stmts = append(stmts, stmt)

		if self.compare(_CASE) && isDefault {
			self.syntaxError("Default case must be last one", false)
		}
	}
	self._loopLevel--

	c.Case = exprl
	c.Body = stmts

	return c
}

func (self *parser) _parseSwitchClause() []*SwitchCase {
	cases := make([]*SwitchCase, 0)

	if self.compare(_RBRACE) {
		return cases
	}

	for !self.compare(_RBRACE) && !self.compare(_EOF) {
		c := self._parseSwitchCase()
		cases = append(cases, c)
	}

	return cases
}

func (self *parser) parseSwitchStmt() *SwitchStmt {
	self.expect(_SWITCH)

	stmt := new(SwitchStmt)
	stmt.pos = *self.pos

	target := self.parseExpression()

	self.expect(_LBRACE)

	clause := self._parseSwitchClause()

	self.want(_RBRACE)

	stmt.Target = target
	stmt.Clause = clause

	return stmt
}

func (self *parser) parseStmt() Statement {
	var stmt Statement

	switch self.tok {

	case _VAR:
		stmt = self.parseVarStmt(false, false, true)

	case _IF:
		stmt = self.parseIfStmt(false)

	case _RETURN:
		stmt = self.parseReturnStmt()

	case _WHILE:
		stmt = self.parseWhileStmt()

	case _FOR:
		stmt = self.parseForStmt()

	case _TRY:
		stmt = self.parseTryStmt()

	case _SWITCH:
		stmt = self.parseSwitchStmt()

	case _BREAK:
		if self._loopLevel == 0 {
			self.syntaxError("Break outside loop block", false)
		}

		b := new(BreakStmt)
		b.pos = *self.pos
		stmt = b
		self.next()
		if self.compare(_IDENTIFIER) {
			b.Label = self.getIdentifier().Value
		}
		self.expect(_SEMI)

	case _CONTINUE:
		if self._loopLevel == 0 {
			self.syntaxError("Continue outside loop block", false)
		}

		c := new(ContinueStmt)
		c.pos = *self.pos
		stmt = c
		self.next()
		if self.compare(_IDENTIFIER) {
			c.Label = self.getIdentifier().Value
		}
		self.expect(_SEMI)

	case _THROW:
		stmt = self.parseThrowStmt()

	case _ASSERT:
		stmt = self.parseAssertStmt()

	case _GOTO:
		self.next() // eat 'goto'
		gto := new(GotoStmt)
		gto.pos = *self.pos

		gto.Label = self.getIdentifier().Value

		self.expect(_SEMI)

		stmt = gto

	case _EOF:
		return nil

	case _SEMI:
		self.next()

	case _OPERATOR, _NUMBER, _IDENTIFIER, _STRING:
		if self.tok == _IDENTIFIER && self.peek().kind == _COLON {
			label := new(LabelStmt)
			label.pos = *self.pos
			label.Label = self.tokValue

			self.next() // eat IDENTIFIER
			self.next() // eat ':'

			stmt = label

			goto rtn
		}

		expt := new(ExprStmt)
		expt.pos = *self.pos

		expr := self.parseExpression()
		expt.Expr = expr

		self.expect(_SEMI)
		stmt = expt

	default:
		self.syntaxError("Expecting Statement, but found "+getTokenName(self.tok), false)
		self.next()
	}

rtn:
	return stmt
}

func (self *parser) parseStmts() []Statement {
	stmts := make([]Statement, 0)

	for !self.compare(_RBRACE) {
		stmt := self.parseStmt()

		if stmt == nil && self.compare(_EOF) {
			break
		}
		stmts = append(stmts, stmt)
	}

	return stmts
}

func (self *parser) _parseMemberProperty(clsName string) (*MemberProperty, bool) {
	// check access
	var accModf uint8 = ACC_DEFAULT

	property := new(MemberProperty)
	property.pos = *self.pos

	if self.tok == _IDENTIFIER && self.tokValue == clsName {
		property.AccessModifiers = ACC_DEFAULT
		return property, false
	} else if self.tok == _IDENTIFIER {
		return property, true
	}

	switch self.tok {

	case _PUBLIC:
		self.next()
		accModf = ACC_PUBLIC
	case _PROTECTED:
		self.next()
		accModf = ACC_PROTECTED
	case _PRIVATE:
		self.next()
		accModf = ACC_PRIVATE
	case _STATIC, _CONST, _IDENTIFIER:
		accModf = ACC_DEFAULT
	}

	// check static and const
	property.AccessModifiers = accModf
	property.IsStatic = self.got(_STATIC)
	property.IsConst = self.got(_CONST)

	noPropertyDecl := !property.IsConst && !property.IsStatic && accModf == ACC_DEFAULT

	return property, noPropertyDecl
}

func (self *parser) parseFieldDeclStmt(property *MemberProperty) *FieldDeclare {
	field := new(FieldDeclare)

	varstmt := self.parseVarStmt(false, false, false)
	if varstmt == nil {
		return nil
	}

	field.Names = varstmt.Names
	field.Type = varstmt.Type
	field.Value = varstmt.Value
	field.Property = property

	return field
}

func (self *parser) parseParameterList() *ParameterList {
	self.expect(_LPAREN)
	plist := new(ParameterList)
	plist.pos = *self.pos

	plainp := make([]*PlainParameter, 0)
	var varp *VarParam

	if self.got(_RPAREN) {
		return plist
	}

	for !self.compare(_RPAREN) && !self.compare(_EOF) {
		name := self.getIdentifier()
		if self.got(_DDD) { // ...
			vpt := self.parseTypeExpr(true)
			varp = new(VarParam)
			varp.pos = *self.pos
			varp.Name = name
			varp.Type = vpt
			break // Var param must be last one!
		}
		pt := self.parseTypeExpr(true)
		p := new(PlainParameter)
		p.pos = *self.pos
		p.Name = name
		p.Type = pt

		plainp = append(plainp, p)

		if !self.got(_COMMA) {
			break
		}
	}

	self.expect(_RPAREN)

	plist.Params = plainp
	plist.VarParam = varp

	return plist
}

func (self *parser) parseMethodDeclOrDefStmt(property *MemberProperty,
	declOnly bool, pos Pos, clsName string) MemberDeclare {

	name := self.getIdentifier()
	if name == nil {
		return nil
	}

	var isConstructor bool

	if name.Value == clsName {
		isConstructor = true

		// check property
		if property.IsStatic || property.IsConst {
			self.posSyntaxError("Constructor cannot be const or static", false,
				name.pos.line, name.pos.col)
		}
	}

	param := self.parseParameterList()

	var rtnType *TypeExpr
	var genTypes *ClassGeneric

	if self.isOperator(_LTH) {
		if isConstructor {
			self.syntaxError("Constructor cannot have generic types", false)
		}

		genTypes = self._parseClsGeneric()
	}

	isNative := self.got(_NATIVE)

	switch self.tok {

	case _SEMI, _LBRACE:
		break
	case _VOID:
		self.next() // eat 'void'
	default:
		rtnType = self.parseTypeExpr(true)
	}

	if rtnType != nil && isConstructor {
		self.syntaxError("Constructor cannot have return value", false)
	}

	mthd := new(MethodDeclare)
	mthd.pos = pos

	mthdef := new(MethodDefine)
	mthdef.pos = pos

	var result MemberDeclare
	var mthB *BlockStmt
	var inDef bool

	if self.compare(_SEMI) && !isNative {
		if isConstructor {
			self.syntaxError("Expecting _LBRACE", false)
		}

		if !declOnly {
			self.syntaxError("Method define only", false)
		}
		self.next()

		mthd.Property = property
		mthd.ReturnType = rtnType
		mthd.Parameters = param
		mthd.Name = name
		mthd.GenericNames = genTypes

		result = mthd
		goto rtnRes
	}

	inDef = true

	if declOnly && inDef && !isConstructor {
		self.syntaxError("Method declaration only", false)
	}

	if isNative {
		mthdef.IsNative = true
		mthdef.ReturnType = rtnType
		mthdef.Property = property
		mthdef.Parameters = param
		mthdef.Body = nil
		mthdef.Name = name
		mthdef.GenericNames = genTypes

		self.expect(_SEMI)

		result = mthdef

		goto rtnRes
	}

	mthB = self.parseBlock(false)

	if isConstructor {
		c := new(ConstructorStmt)
		c.pos = pos
		c.Body = mthB
		c.Name = name
		c.Params = param
		c.Property = property

		result = c
	} else {
		mthdef.ReturnType = rtnType
		mthdef.Property = property
		mthdef.Parameters = param
		mthdef.Body = mthB
		mthdef.Name = name
		mthdef.GenericNames = genTypes

		result = mthdef
	}

rtnRes:
	return result
}

func (self *parser) parseMemberDeclareStmt(mthDeclOnly bool, clsName string) MemberDeclare {
	pos := *self.pos

	prop, nodecl := self._parseMemberProperty(clsName)

	if nodecl {
		switch self.tok {
		case _FUNC:
			self.next() // eat 'func'
			return self.parseMethodDeclOrDefStmt(prop, mthDeclOnly, pos, clsName)
		case _VAR:
			self.next() // eat 'var'
			fd := self.parseFieldDeclStmt(prop)
			fd.pos = pos
			return fd
		case _CLASS, _INTERFACE:
			cls := self.parseClassOrInterfaceDecl(prop, true)
			return cls

		case _ENUM:
			cls := self.parseEnumDecl(prop, true)
			return cls
		}
	}

	if self.compare(_CLASS) || self.compare(_INTERFACE) {
		cls := self.parseClassOrInterfaceDecl(prop, true)
		return cls
	}

	if self.compare(_IDENTIFIER) && !nodecl {
		ptok := self.peek()
		if ptok.kind == _LPAREN {
			return self.parseMethodDeclOrDefStmt(prop, mthDeclOnly, pos, clsName)
		}
		fd := self.parseFieldDeclStmt(prop)
		fd.pos = pos
		return fd
	} else {
		self.syntaxError("Expecting access declaration or property declaration", false)
		self.next()
		return nil
	}
}

func (self *parser) parseOpOverloadDef() *OperatorOverloadDecl {
	self.expect(_OPERATOR_OVL)

	decl := new(OperatorOverloadDecl)
	decl.pos = *self.pos

	var op operator

	// check is identifier or not
	if self.compare(_IDENTIFIER) {
		ok := false
		if _, ok = validOverloadOpNames[self.tokValue]; !ok {
			self.syntaxError("Invalid operator name", false)
		}
		opn := self.getIdentifier()
		if ok {
			op = validOverloadOpNames[opn.Value]
		} else {
			op = _PLUS
		}

		goto nameOp
	}

	if self.tok == _LBRACK || self.tok == _LBRACE || self.tok == _LPAREN {
		if self.tok == _LBRACE || self.tok == _LPAREN {
			self.syntaxError("Invalid operator", false)
		}

		self.tok = _OPERATOR
		self.tokOp = _OP_SUBSCR
	}

	if self.tok != _OPERATOR {
		self.syntaxError("Not an operator", false)
		op = _PLUS // Set an default op
	} else {
		op = self.tokOp
	}

	if self.tokOp == _OP_SUBSCR {
		self.next()                                                     // eat '['
		_ = self.got(_RPAREN) || self.got(_RBRACE) || self.got(_RBRACK) // ||
		// self.got(_LPAREN) || self.got(_LBRACE) || self.got(_LBRACK)
		// Jump over the right part
	} else {
		self.next() //eat op
	}

	if !isValidOverloadOp(op) {
		self.syntaxError("Invalid operator", false)
		self.next()
	}

nameOp:

	if !self.compare(_LPAREN) {
		self.syntaxError("Expecting _LPAREN", false)
	}

	param := self.parseParameterList()
	if len(param.Params) != 1 {
		self.syntaxError("OpOverload parameter's length must be 1", false)
	}

	if param.VarParam != nil {
		self.syntaxError("OpOverload cannot have variable parameter", false)
	}

	var rtnT *TypeExpr
	var clsG *ClassGeneric

	if self.isOperator(_LTH) {
		clsG = self._parseClsGeneric()
	}

	if self.compare(_LBRACE) || self.tok == _VOID || self.isOperator(_LTH) {
		if self.tok == _VOID {
			self.next()
		}
		self.syntaxError("OpOverload must have return value", false)
	} else {
		rtnT = self.parseTypeExpr(true)
	}

	body := self.parseBlock(false)

	decl.Op = op
	decl.Body = body
	decl.Params = param
	decl.ReturnType = rtnT
	decl.GenericNames = clsG

	return decl
}

func (self *parser) parseClassBody(clsName string,
	isInterface bool) ([]MemberDeclare, []*OperatorOverloadDecl) {
	self.expect(_LBRACE)

	var decl MemberDeclare

	ovloads := make([]*OperatorOverloadDecl, 0)
	decls := make([]MemberDeclare, 0)

	for !self.compare(_RBRACE) && !self.compare(_EOF) {
		switch self.tok {

		case _OPERATOR_OVL:
			if isInterface {
				self.syntaxError("Interface Decl cannot have operator overload decl", false)
			}

			ovl := self.parseOpOverloadDef()

			if ovl != nil {
				ovloads = append(ovloads, ovl)
			}
		default:
			decl = self.parseMemberDeclareStmt(isInterface, clsName)

			if decl != nil {
				decls = append(decls, decl)
			}
		}
	}

	self.expect(_RBRACE)

	return decls, ovloads
}

func (self *parser) _parseClsGeneric() *ClassGeneric {
	self.expectOp(_LTH)

	clsg := new(ClassGeneric)
	clsg.pos = *self.pos

	names := make([]*Identifier, 0)

	fn := self.getIdentifier()
	if fn == nil {
		return clsg
	}

	names = append(names, fn)

	for self.got(_COMMA) {
		name := self.getIdentifier()
		names = append(names, name)
	}

	self.expectOp(_GTH)

	clsg.ClassNames = names

	return clsg
}

func (self *parser) parseEnumItem() *EnumItem {
	item := new(EnumItem)
	item.pos = *self.pos

	n := self.getIdentifier()
	var v *CellExpr

	if self.isOperator(_ASSIGN) {
		self.next() // eat '='
		if self.compare(_NUMBER) {
			ok := false
			v, ok = self.parseCellExpr().(*CellExpr)
			if !ok {
				self.syntaxError("Expecting NUMBER", false)
			}
		} else {
			self.syntaxError("Expecting NUMBER", false)
		}
	}

	item.Name = n
	item.Value = v

	return item
}

func (self *parser) parseEnumDecl(property *MemberProperty, canStatic bool) *EnumDeclare {
	self.expect(_ENUM)

	if property.IsConst || (property.IsStatic && !canStatic) {
		self.syntaxError("Enum declaration cannot be static or const", false)
	}

	decl := new(EnumDeclare)
	decl.pos = *self.pos

	name := self.getIdentifier()
	items := make([]*EnumItem, 0)

	self.expect(_LBRACE)

	for !self.compare(_RBRACE) && !self.compare(_EOF) {
		i := self.parseEnumItem()
		items = append(items, i)

		if !self.got(_SEMI) {
			break
		}
	}

	self.expect(_RBRACE)

	decl.Name = name
	decl.Property = property
	decl.ItemList = items

	return decl
}

func (self *parser) parseClassOrInterfaceDecl(property *MemberProperty,
	canStatic bool) MemberDeclare {
	// check property
	if property.IsConst || (property.IsStatic && !canStatic) {
		self.syntaxError("class Decl cannot be static or const in this case", false)
	}

	clsDecl := new(ClassDeclare)
	intfDecl := new(InterfaceDeclare)
	clsDecl.pos = *self.pos
	intfDecl.pos = *self.pos
	var isInterface bool

	if self.got(_INTERFACE) {
		isInterface = true
	} else {
		self.expect(_CLASS)
	}

	clsName := self.getIdentifier()

	var generic *ClassGeneric
	extCls := make([]*ClassAccessExpr, 0)
	interfaces := make([]*ClassAccessExpr, 0)

	if self.isOperator(_LTH) {
		generic = self._parseClsGeneric()
	}

	if self.got(_LPAREN) {
		extCls = append(extCls, self.parseClassAccessExpr())

		if isInterface {
			for self.got(_COMMA) {
				extCls = append(extCls, self.parseClassAccessExpr())
			}
		}

		self.expect(_RPAREN)
	}

	if self.got(_LARROW) {
		for !self.compare(_LBRACE) || !self.compare(_EOF) {
			c := self.parseClassAccessExpr()
			interfaces = append(interfaces, c)

			if !self.got(_COMMA) {
				break
			}
		}
	}

	cName := clsName.Value

	mbrs, ovls := self.parseClassBody(cName, isInterface)

	if !isInterface {
		clsDecl.Property = property
		if len(extCls) > 0 {
			clsDecl.ExtendsClass = extCls[0]
		}
		clsDecl.GenericTypes = generic
		clsDecl.InterfaceNames = interfaces
		clsDecl.Members = mbrs
		clsDecl.OpOverloads = ovls
		clsDecl.Name = clsName

		return clsDecl

	} else {
		intfDecl.ExtendsInterfaces = extCls
		intfDecl.InterfaceNames = interfaces
		intfDecl.Name = clsName
		intfDecl.Property = property
		intfDecl.GenericTypes = generic
		intfDecl.MethodDeclarations = mbrs

		return intfDecl
	}
}

func (self *parser) parseOutsideDecls() []MemberDeclare {
	decls := make([]MemberDeclare, 0)

	var decl MemberDeclare

	for !self.compare(_EOF) {
		prop, _ := self._parseMemberProperty("")
		if prop.IsConst {
			self.syntaxError("Outside class or interface cannot be const",
				false)
		}

		switch self.tok {

		case _CLASS, _INTERFACE:
			decl = self.parseClassOrInterfaceDecl(prop, false)
		case _ENUM:
			decl = self.parseEnumDecl(prop, false)
		default:
			self.syntaxError("Expecting declaration", false)
			self.next()
		}

		decls = append(decls, decl)
	}

	return decls
}

func TestParser(reader io.Reader) (expr interface{}, ok bool) {
	p := parser{}
	p.init(reader, "TEST")
	p.next()

	return p.parseClassFile(""), !p.hasError
}
